package cn.agiledata.bank.transaction.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.hibernateBean.SubAccount;
import cn.agiledata.bank.hibernateBean.TransDetail;
import cn.agiledata.bank.hibernateBean.Transaction;
import com.vnv.infrastructure.logic.IPBHibernate3BaseMgr;


public class TransactionDetailOperate extends IPBHibernate3BaseMgr
	implements TransactionDetail{
	private FeeRatioInterf feeRatio;
	
		
	
	
	//客户账户变化额
	//private double customerAccountChange =0;
	
	public PackTransactionDetail ptd = new PackTransactionDetail();

	public void fillDepositByDownSite(Transaction tran, List bankList,String str) {
		// TODO Auto-generated method stub
		ptd = new PackTransactionDetail();
		fillTranForFeeInfo(tran);
	
		ptd.transactionBetweenBankAndCustomer(tran,bankList,str,tran.getAmount());
		
		SubAccount chargeAccount = ((SubAccount)bankList.get(2));
		Double returnValue = 
			ptd.transactionDetailForYSX(tran, chargeAccount, tran.getCredit(),tran.getCreditFee());
		((SubAccount)bankList.get(2)).getAccountBalance().setBalance(returnValue);
		//this.getAhoi().update(((SubAccount)bankList.get(2)));
		
		ptd.finalAccountCreditInfo(tran);
	}
	
	
	public void fillGainTransaction(Transaction tran, List bankList) {
		fillTranForFeeInfo(tran);
		ptd = new PackTransactionDetail();
		double debitFee = tran.getAmount().doubleValue();
		remit(tran, bankList, debitFee);	
		ptd.finalAccountDebitInfo(tran);
	}
	public void fillGainTransacionPatternT2(Transaction tran, List bankList) {
		// TODO Auto-generated method stub
		fillTranForFeeInfo(tran);
		ptd = new PackTransactionDetail();
		double debitFee = tran.getAmount().doubleValue()-tran.getDebitFee().doubleValue();
		remit(tran, bankList, debitFee);	
		ptd.finalAccountDebitInfo(tran);
	}
	
	private void remit(Transaction tran, List bankList, double amount) {
		ptd = new PackTransactionDetail();
		ptd.transactionWithGainMoney(amount,tran,bankList);
		
		//收费账户计算记录
		SubAccount chargeAccount = ((SubAccount)bankList.get(2));
		//REMARK : RETURN MONEY 部分退款的费率为零, 即:部分退款,不退手续费;全部退款,退手续费.
		Double debitFee = tran.getDebitFee();
		if (tran.getReturnAmount() != null 
				&& (tran.getReturnAmount().doubleValue()+tran.getAmount().doubleValue() != 0)) {
			debitFee = new Double(0);
		}
		Double returnValue = 
			ptd.transactionDetailForYSX(tran, chargeAccount, tran.getDebit(),debitFee);
		((SubAccount)bankList.get(2)).getAccountBalance().setBalance(returnValue);
		((SubAccount)bankList.get(2)).setChanged(true);
		//this.getAhoi().update((SubAccount)bankList.get(2));
		
		//tran.getDebit().getAccountBalance().setBalance(
		//		new Double(tran.getDebit().getAccountBalance().getBalance().doubleValue()+customerAccountChange));	
		
		tran.setCreditFee(new Double(0));
	}
	public void fillTransactionDetailForFree(Transaction tran, List bankList) {
		fillTranForFeeInfo(tran);
		ptd = new PackTransactionDetail();
		ptd.transactionBetweenBankAndCustomer(tran,bankList,Constant.INITIAL_ACCOUNT_BANK,tran.getAmount());		
		
		ptd.finalAccountCreditInfo(tran);
		
		tran.setCreditFee(new Double(0));
		tran.setDebitFee(new Double(0));
	}

	/* 
	 * 如果是银行收费且支付系统向客户收费
	 */
	public void fillTransactionDetail(Transaction tran, List bankList ) {
		fillTranForFeeInfo(tran);
		ptd = new PackTransactionDetail();
		//银行账户和客户账户间的资金转移
		ptd.transactionBetweenBankAndCustomer(tran,bankList,Constant.INITIAL_ACCOUNT_BANK,
				new Double(tran.getAmount().doubleValue()-tran.getDebitFee().doubleValue()));		
		//垫付基金支出记录
		transactionWithDraw(tran, bankList);		
		//收费账户计算记录
		transactionWithChargeAccount(tran, bankList);
		
		ptd.finalAccountCreditInfo(tran);
	}
	/**
	 * 对费率的操作，获得费率接口，填充交易信息
	 * 
	 * @param tran
	 */
	private void fillTranForFeeInfo(Transaction tran) {
			tran.setDebitfeeRatio(feeRatio.getDebitRatioHis(tran));
			tran.setCreditfeeRatio(feeRatio.getCreditRatioHis(tran));
			if(tran.getDebitfeeRatio() != null && tran.getDebitfeeRatio().longValue()==0) {
				tran.setDebitfeeRatio(null);
			}
			if(tran.getCreditfeeRatio() != null && tran.getCreditfeeRatio().longValue()==0) {
				tran.setCreditfeeRatio(null);
			}
			
			tran.setDebitFee(new Double(feeRatio.getDebitFee(tran)));
			tran.setCreditFee(new Double(feeRatio.getCreditFee(tran)));
	}
	
	/*
	 * 如果只是银行收费，支付系统不收费
	 */
	public void fillTransactionDetailWithOnYSX(Transaction tran, List bankList ){
		fillTranForFeeInfo(tran);
		ptd = new PackTransactionDetail();
		//fillTranForFeeInfo(tran);		
		
		//银行账户和客户账户间的资金转移
		ptd.transactionBetweenBankAndCustomer(tran,bankList,Constant.INITIAL_ACCOUNT_BANK
				,new Double(tran.getAmount().doubleValue()-tran.getDebitFee().doubleValue()));		
		//垫付基金支出记录
		transactionWithDraw(tran, bankList);
		ptd.finalAccountCreditInfo(tran);
		
		tran.setCreditFee(new Double(0));
	}
	

	/**
	 * 账对收费账户进行的操作
	 * 如果收费的话，调用此方法
	 * author  joe
	 * date    2006-03-29
	 * @param tran
	 * @param bankList
	 */
	
	private void transactionWithChargeAccount(Transaction tran, List bankList) {
		SubAccount chargeAccount = ((SubAccount)bankList.get(2));
		
		//以下是收费账户
		
		Double returnValue = 
			ptd.transactionDetailForYSX(tran, chargeAccount, tran.getCredit(),tran.getCreditFee());
		((SubAccount)bankList.get(2)).getAccountBalance().setBalance(returnValue);
	//	this.getAhoi().update(((SubAccount)bankList.get(2)));

	}

/**
 * 账对垫付账户所做的操作，如果存在垫付金额，即银行收费，调用此方法
 * author  joe
 * date    2006-03-29
 * @param tran
 * @param bankList
 */
	private void transactionWithDraw(Transaction tran, List bankList) {
		SubAccount drawAccount = ((SubAccount)bankList.get(1));
		//以下是垫付账户所缴金额
		TransDetail td1 = new TransDetail();
		td1.setAmount(new Double(-tran.getDebitFee().doubleValue()));
		
		Double returnValue = 
			ptd.transactionDetailForYSX(tran, drawAccount, tran.getCredit(),new Double(-tran.getDebitFee().doubleValue()));
		
		((SubAccount)bankList.get(1)).getAccountBalance().setBalance(returnValue);
	}

/**
 * 用来反射的内部类，账对每个public方法都需要加载的公共私有方法所实现，
 * 用统一的动态方法调用所有的方法，达到aop的效果，因为使用spring封装的
 * aop不宜实现，
 * author： joe
 * date  ： 2006-04-03
 * @author user
 *
 */

	class transactionDetailHandler implements InvocationHandler{
		Object obj =new Object();
		public Object bind() {
			Object resultObj = new Object();
			try {
				Class cla = Class.forName("cn.agiledata.bank.impl.TransactionDetailOperate");
				obj = cla.newInstance();
				resultObj = Proxy.newProxyInstance(obj.getClass().getClassLoader(),
						obj.getClass().getInterfaces(), this);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return resultObj;
		}
		
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			// TODO Auto-generated method stub
			Object returnProxy = proxy;

				fillTranForFeeInfo((Transaction)args[0]);
				
				returnProxy = method.invoke(obj,args);
				
			return returnProxy;
		}
		
	}


	public void fillPayTransaction(Transaction tran, List bankList) {
	// TODO Auto-generated method stub
		fillTranForFeeInfo(tran);
		double amount = tran.getAmount().doubleValue();
		remit(tran, bankList, amount);
		ptd.finalAccountDebitInfo(tran);
	}



	public void setFeeRatio(FeeRatioInterf feeRatio) {
		this.feeRatio = feeRatio;
	}


}
